package io.shuttle.mbe.api

import io.shuttle.mbe.api.annotation.ChromeMinVersion
import io.shuttle.mbe.api.annotation.PromiseStyleMinVersion
import io.shuttle.mbe.api.types.Value1Function
import io.shuttle.mbe.api.types.VoidFunction
import io.shuttle.mbe.core.Promise

////////////////////
// Types
////////////////////
/**
 * The `Browser.types` API contains type declarations for Chrome.
 */
interface ChromeSetting<T> {
    // Fired after the setting changes.
     val onChange: Events.Event<Value1Function<GetResult<T>>>

    @PromiseStyleMinVersion(96)
     fun clear(details: ClearDetails?, callback: VoidFunction? = null): Promise<Void>

    @PromiseStyleMinVersion(96)
     fun get(
        details: GetDetails,
        callback: Value1Function<GetResult<T>>? = null
    ): Promise<GetResult<T>>

    @PromiseStyleMinVersion(96)
     fun set(details: SetDetails<T>, callback: VoidFunction? = null): Promise<Void>


    @ChromeMinVersion(44)
    enum class ChromeSettingScope {
        // regular: setting for the regular profile (which is inherited by the incognito profile if not overridden elsewhere),
        regular,

        // regular\_only: setting for the regular profile only (not inherited by the incognito profile),
        regular_only,

        // incognito\_persistent: setting for the incognito profile that survives browser restarts (overrides regular preferences),
        incognito_persistent,

        // incognito\_session\_only: setting for the incognito profile that can only be set during an incognito session and is deleted when the incognito session ends (overrides regular and incognito_persistent preferences).
        incognito_session_only
    }

    @ChromeMinVersion(44)
    enum class LevelOfControl {
        // not\_controllable: cannot be controlled by any extension
        not_controllable,

        // controlled\_by\_other\_extensions: controlled by extensions with higher precedence
        controlled_by_other_extensions,

        // controllable\_by\_this\_extension: can be controlled by this extension
        controllable_by_this_extension,

        // controlled\_by\_this\_extension: controlled by this extension
        controlled_by_this_extension
    }

    data class GetDetails(
        // Whether to return the value that applies to the incognito session (default false).
        var incognito: Boolean?,
    )

    data class GetResult<T>(
        // Whether the effective value is specific to the incognito session. This property will only be present if the incognito property in the details parameter of get() was true.
        var incognitoSpecific: Boolean?,
        var levelOfControl: LevelOfControl,
        var value: T,
    )

    data class ClearDetails(
        // Where to clear the setting (default: regular).
        var scope: ChromeSettingScope?,
    )

    data class SetDetails<T>(
        // Where to set the setting (default: regular).
        var scope: ChromeSettingScope?,
        // The value of the setting. Note that every setting has a specific value type, which is described together with the setting. An extension should not set a value of a different type.
        var value: T
    )
}